﻿namespace GoodAdmin.System;

public class DictDataService : DbRepository<SysDictData>, IDictDataService, ITransient
{
    private readonly IRedisCacheManager _redisCacheManager;

    public DictDataService(IRedisCacheManager redisCacheManager)
    {
        _redisCacheManager = redisCacheManager;
    }
    public async Task Add(DictDataAddInput input)
    {
        await CheckInput(input);
        if(await InsertAsync(input))
        {
            RefreshCache(input.DictTypeId);
        }        
    }

    public async Task Delete(BaseIdInput input)
    {
        var dictData = await GetDetail(input.Id);        
        if(await DeleteAsync(it => it.Id == input.Id))
        {
            RefreshCache(dictData.DictTypeId);
        }
    }

    public async Task<SysDictData> GetDetail(long DictDataId)
    {
        var list = await GetDictDataList();
        return list.FirstOrDefault(it => it.Id == DictDataId);
    }

    public async Task<List<SysDictData>> GetDictDataList(long DictTypeId)
    {
        var dictDataList = await GetDictDataList();
        return dictDataList.Where(it => it.DictTypeId == DictTypeId).ToList();
    }

    public async Task<List<SysDictData>> GetDictDataList()
    {
        string key = CacheConst.SysDictData;
        var dictDataList = _redisCacheManager.Get<List<SysDictData>>(key);
        if (dictDataList == null)
        {
            dictDataList = await GetListAsync();
            _redisCacheManager.Set(key, dictDataList);
        }
        return dictDataList;
    }

    public async Task<SqlSugarPagedList<SysDictData>> GetDictDataPageList(DictDataPageInput input)
    {
        return await Context.Queryable<SysDictData>()
            .WhereIF(input.DictTypeId > 0, it => it.DictTypeId == input.DictTypeId)
            .WhereIF(!string.IsNullOrWhiteSpace(input.DictDataName),it=>it.Name.Contains(input.DictDataName))
            .OrderBy(it => it.SortCode)
            .ToPagedListAsync(input.PageIndex, input.PageSize);
    }

    public async Task Update(DictDataUpdateInput input)
    {
        await CheckInput(input);
        var dictData = await GetDetail(input.Id);
        if(await UpdateAsync(input))
            //更新前后的类型对应的cache都得清除
            RefreshCache(new List<long> { input.DictTypeId, dictData.DictTypeId });
    }

    #region
    private async Task CheckInput(SysDictData dict)
    {
        var dictList = await GetDictDataList();
        
        //判断父节点是否存在
        //if (dict.ParentId > 0 && !dictList.Any(it => it.Id == dict.ParentId))
        //{
        //    throw Oops.Bah(DictErrorCode.D003);
        //}        
       
        //判断同一字典类型下是否存在相同name或者code的数据
        if (dictList.Any(it =>it.DictTypeId==dict.DictTypeId && it.Value == dict.Value && it.Id != dict.Id))
        {
            throw Oops.Bah(DictErrorCode.D005);
        }
        if (dictList.Any(it => it.DictTypeId == dict.DictTypeId && it.Name == dict.Name && it.Id != dict.Id))
        {
            throw Oops.Oh(DictErrorCode.D004);
        }
        //如果Id大于0，表示更新
        if(dict.Id>0 && !dictList.Any(it => it.Id == dict.Id))
        {
            throw Oops.Oh(DictErrorCode.D006);
        }        
    }

    private void RefreshCache(long DictTypeId)
    {
        RefreshCache(new List<long> { DictTypeId });
    }
    private void RefreshCache(List<long> DictTypeIds)
    {
        //移除每个字典类型对应的字典数据
        foreach(var dictTypeId in DictTypeIds)
        {
            _redisCacheManager.Remove(CacheConst.SysDictData + dictTypeId);
        }
        //移除全部字典数据
        _redisCacheManager.Remove(CacheConst.SysDictData);
    }
    #endregion
}